package pkg

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"k8s.io/klog"
	"net"
	"strings"
	"time"
)

const SUCCESS = "SUCCESS"
const NOTFOUND = "NOTFOUND"
const FAILED = "FAILED"

type executor struct {
	c net.Conn
	stepsFile string
	wineImageDir string
	imageButton imageButton
	steps     []*Step
	snapshots []Button
	pi int
	end int
	successNum int
	failedNum int

}
func newExecutor(stepsFile string,wineImageDir string,c net.Conn,imageButton imageButton)(*executor,error){
	e:=&executor{
		stepsFile: stepsFile,
		wineImageDir: wineImageDir,
		imageButton: imageButton,
		c: c,
		successNum: 0,
		failedNum: 0,
	}
	err:=e.init()
	return e,err
}

func (e *executor)init()error{
	e.pi=0
	e.end=0
	e.steps=[]*Step{}

	// get steps
	bytes,err:=ioutil.ReadFile(e.stepsFile)
	if err!=nil{
		fmt.Printf("read file %s with error:%v\n",e.stepsFile,err)
		return err
	}

	strs:=strings.Split(string(bytes),"\n")
	for _,str:=range strs{
		if len(str)==0{
			continue
		}
		attrs:=strings.Split(str,"\t")
		step:=&Step{
			name: strings.TrimSpace(attrs[0]),
		}
		e.snapshots=append(e.snapshots,Button{Name: step.name,ButtonType: ButtonTYPE})
		e.steps=append(e.steps,step)
		e.end++
	}
	return nil
}


func(e *executor)exec()(error,bool){//error,exit
	time.Sleep(2*time.Second)
	if e.pi>e.end{
		klog.Infof("the testfile %s run success\n",e.stepsFile)
		return nil,true
	}
	cmd:=fmt.Sprintf("LINX_CMD_CLICK_BUTTON %s",e.steps[e.pi].name)
	_, err := e.c.Write([]byte(cmd))
	if err != nil {
		klog.Errorf("Write error: %v\n", err)
		return err,true
	}

	buf := make([]byte, 10240)
	nr, err := e.c.Read(buf)
	if err != nil {
		klog.Errorf("Read error: %v\n", err)
		return err,true
	}
	data := buf[0:nr]
	data=bytes.Trim(data,"\x00")
	klog.Infof("Server got:%v\n", string(data))
	msgAction:=MsgAction{}
	err=json.Unmarshal(data,&msgAction)
	if err!=nil{
		klog.Infof("unmarshal error:%v\n",err)
		return err,true
	}
	if msgAction.MsgType!=MSG_TYPE_ACTION{
		klog.Errorf("%v",msgAction)
		klog.Infof("msg type error,expected %d but %d",MSG_TYPE_ACTION,msgAction.MsgType)
		return fmt.Errorf("msg type error,expected %d but %d",MSG_TYPE_GET_BUTTONS,msgAction.MsgType),true
	}
	if msgAction.Result==SUCCESS{
		klog.Infof("Run step %v success",e.steps[e.pi])
		e.pi++
		return nil,false
	}else if msgAction.Result==NOTFOUND{
		klog.Infof("Button not found for command %v",e.steps[e.pi])
		return nil,true
	}else if msgAction.Result==FAILED{
		klog.Infof("Run step %v failed",e.steps[e.pi])
		return nil,true
	}else{
		klog.Infof("Recv %s not valid",data)
		return nil,true
	}
}
func(e *executor)get_buttons()([]Button,error) { //error,exit
	time.Sleep(20*time.Second)
	imagePath:=fmt.Sprintf("%s/%d.png",e.wineImageDir,e.pi)
	err:=captureImage(e.imageButton,imagePath)
	if err!=nil{
		klog.Errorf("capture image error:%v",err)
		return nil, err
	}

	_, err = e.c.Write([]byte("LINX_CMD_GET_BUTTON_LIST"))
	if err != nil {
		klog.Errorf("Write error: %v\n", err)
		return nil,err
	}

	buf := make([]byte, 10240)
	nr, err := e.c.Read(buf)
	if err != nil {
		return nil,err
	}
	data := buf[0:nr]
	data=bytes.Trim(data,"\x00")
	klog.Infof("Server got:%v\n", string(data))


	msgButton:=MsgButton{}
	err=json.Unmarshal(data,&msgButton)
	if err!=nil{
		klog.Infof("unmarshal error:%v\n",err)
		return nil,err
	}
	if msgButton.MsgType!=MSG_TYPE_GET_BUTTONS{
		klog.Errorf("%v",msgButton)
		klog.Infof("msg type error,expected %d but %d",MSG_TYPE_GET_BUTTONS,msgButton.MsgType)
		return nil,fmt.Errorf("msg type error,expected %d but %d",MSG_TYPE_GET_BUTTONS,msgButton.MsgType)
	}
	return msgButton.Buttons,nil
}

func (e *executor)isFinished()bool{
	return e.c==nil || e.pi>=e.end
}
